/*
 * main.c
 * This file is part of COOG
 *
 * Copyright (C) 2012 - Luke Westby & Jon Gautsch
 *
 * COOG is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * COOG is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with COOG. If not, see <http://www.gnu.org/licenses/>.
 */

#include "synth.h"

int main(int argc, char **argv){

/* variables ---------------------------------------------------------------- */
	
	// user input
	char c;
	int exit = 0;
	
	// phasing - frequency separation
	float diff = 1.0;

	// volume control
	float vol = 1.0;
	
	// pointers to the waveforms the user has selected
	float *wave_1, *wave_2;
	wave_1 = wave_2 = NULL;
	
	// actual waveforms the user can select
	float *sine, *saw, *sqr;
	sine = saw = sqr = NULL;
	
	// frequency lookup table for notes
	double *freqs = NULL;
	
	// PulseAudio context
	pa_simple *s = NULL;

/* initialize audio context ------------------------------------------------- */

	// init the audio card
	s = init_soundcard();
	
	// init the waveforms
	sine = (float *)malloc(sizeof(float) * WAVESIZE);
	saw = (float *)malloc(sizeof(float) * WAVESIZE);
	sqr = (float *)malloc(sizeof(float) * WAVESIZE);
	init_wavetables(saw, sqr, sine);
	
	// init the frequency lookup table
	freqs = (double *)malloc(sizeof(double) * NNOTES);
	init_freqtable(freqs);
	
    wave_1 = wave_2 = saw;

/* open and construct the display ------------------------------------------- */

	// open window
    gfx_open(WINDOW_X, WINDOW_Y, "The COOG - Luke and Jon's Monophonic Synth");

	// draw gui
    draw_piano_roll(95, 560);
    draw_wave_selection_numbers( WINDOW_X/2 - 120, 145, 40);
    word(100, 40, "SELECT WAVEFORM", 3);
    word(15, WINDOW_Y-20, "A Luke Westby and Jon Gautsch Product", 1);
    word(100, 390, "Key map", 1);
    draw_waveform_boxes(WINDOW_X/2 - 60, 100);

	// disable keyboard repeat on X server
	gfx_set_repeat(0);

    
/* main loop ---------------------------------------------------------------- */

    while(!exit){
        
        // get a keypress
        
		c = gfx_wait();
				
		// this switch statement is big, bear with us
		
		// the user can do any of the following:
		// quit
		// change the volume
		// change the phase difference between the two waveforms
		// select which waveforms to use
		// play a note
        switch(c){
                            
            // Quit the program
            case '9':
            	puts("Exiting");
				exit = 1;
                return 0;

			// volume control
            case '7':
                // increase volume
                vol += .1;
                if(vol >= 1.0) vol = 1.0;
                printf("Volume: %f\n", vol);
                break;

            case '8':
                // decrease volume
                vol -= .1;
                if(vol <= 0.0) vol = 0.0;
                printf("Volume: %f\n", vol);
                break;
                
			// phase difference control
            case ',':
                // increase the phase difference value
                diff += .001;
                printf("Oscillator 2 Detune: %f\n", diff);
                break;

            case '.':
                // decrease the phase difference value
                diff -= .001;
                break;

			// waveform 1 selection
            case '1':
                // Select a sine wave as the waveform 1
                wave_1 = sine;
                puts("Oscillator 1 Waveform: sine");
                printf("Oscillator 2 Detune: %f\n", diff);
                break;
            case '2':
                // Select a sawtooth wave as the waveform 1
                wave_1 = saw;
                puts("Oscillator 1 Waveform: saw");
                break;
            case '3':
                // Select a square wave as the waveform 1
                wave_1 = sqr;
                puts("Oscillator 1 Waveform: sqr");
                break;
                
            
			// waveform 2 selection
            case '4':
                // Select a sine wave as the waveform 2
                wave_2 = sine;
                puts("Oscillator 2 Waveform: sine");
                break;
            case '5':
                // Select a sawtooth wave as the waveform 2
                wave_2 = saw;
                puts("Oscillator 2 Waveform: saw");
                break;
            case '6':
                // Select a square wave as the waveform 2
                wave_2 = sqr;
                puts("Oscillator 2 Waveform: sqr");
                break;

        }//end switch
        
		process(c, wave_1, wave_2, freqs, diff, vol, s);
        
    }//end while loop
	
	// drain the audio buffer    
    drain(s);
    
    // supposed to reset keyboard repeat, not sure if it actually works though
	gfx_set_repeat(1);
	
	// clear heap mem
    cleanup(saw, sqr, sine, freqs, s);
    
    return 0;
    
}//end main

/* -------------------------------------------------------------------------- *
 * cleaup()
 * several calls to free to clear heap mem
 * -------------------------------------------------------------------------- */

void cleanup(float *saw, float *sqr, float *sine, double *freqs, pa_simple *s) {
	
	if(saw) free(saw);
	if(sqr) free(sqr);
	if(sine) free(sine);
	if(freqs) free(freqs);
	pa_simple_free(s);
}
